package ruletree.rule;

import java.io.File;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JOptionPane;

import lexicon.Form;
import lexicon.FormList;

import org.jdom2.Content;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;

import ruletree.Folder;
import ruletree.RuleTree;

import view.grammardevelopment.FileSaveLoad;

import components.Children;
import components.Component;
import components.InputXMLDocument;
import features.Feature;
import features.FeatureList;

public class Rule extends RuleTree {

	public static final String INPUT = "input";
	public static final String OUTPUT = "output-actions";

	private Children childrenList;
	private ArrayList<Action> actionList;

	public Rule(String name){
		super(name);
		childrenList = new Children(null);
		actionList = new ArrayList<>();
	}


	public Children getChildrenList() {
		return childrenList;
	}

	public void setChildrenList(Children childrenList) {
		this.childrenList = childrenList;
	}

	public ArrayList<Action> getActionList() {
		return actionList;
	}

	public void setActionList(ArrayList<Action> actionList) {
		this.actionList = actionList;
	}
	
	public void addAction(Action a){
		actionList.add(a);
	}

	public static ArrayList<Action> loadRight(Element node) {
		ArrayList<Action> actionList = new ArrayList<>();
		List<Element> children = node.getChildren();

		for (Element child : children) {
			String name = child.getAttributeValue(Component.ATTRIBUTE_NAME);
			String var = child.getAttributeValue(Component.ATTRIBUTE_VAR);
			Action action = new Action(name);
			action.setVar(var);

			if (child.getChild("component") != null) {
				Children nodes = new Children(null);
				nodes.addChild(Component.createInstance(child.getChild("component"), false));
				action.setChildren(nodes);
			}

			if (child.getChild("features") != null) {
				FeatureList featurelist = new FeatureList(null);
				List<Element> features = child.getChild("features").getChildren();
				for (Element feature : features) {
					String atr = feature.getAttributeValue(Feature.ATTRIBUTE_NAME);
					String value = feature.getAttributeValue(Feature.ATTRIBUTE_VALUE);
					Feature feat = new Feature(atr, value, false);
					featurelist.setFeature(feat);
				}
				
				action.setFeatureList(featurelist);

			}
			if(child.getChild("forms") != null){
				ArrayList<Form> fList = new ArrayList<>();
				
				List<Element> forms = child.getChildren("forms").get(0).getChildren();
				for(Element f: forms){
					Form form = new Form(f.getAttributeValue("name"));
					fList.add(form);
				}
				FormList formList = new FormList(fList);
				action.setForm(formList);
			}
			actionList.add(action);
		}

		return actionList;
	}
	
	public void addChildren(Component component){
		System.out.println(component.getName() + " IM IN ADDCHILDREN RULE");
		childrenList.addChild(component);
		System.out.println(childrenList.getChildren().size() + "IM IN ADD CHILDRen RULE");
		
	}

	public static Rule createInstance(Element rootNode) {
		
		String ruleName = rootNode.getAttributeValue("name");
		//if(rootNode != null)
			//System.out.println("Helllooo");
		Children child = new Children(new ArrayList<Component>());
		Rule rule = new Rule(ruleName);
		//System.out.println(rule != null);
		try {
			// get the left hand side (node) of the rule
			Element leftNode = rootNode.getChild(INPUT);
			// get the right hand side (node) of the rule
			Element rightNode = rootNode.getChild(OUTPUT);
			//System.out.println(leftNode);
			
			if(leftNode.getChildren().size() > 0){
				List<Element> children = leftNode.getChildren();
				for (Element e : children) {
					child.addChild(Component.createInstance(e, true));
				
				}
				rule.setChildrenList(child);
			}
			if(rightNode.getChildren() != null){
				rule.setActionList(loadRight(rightNode));
			}

			return rule;

		} catch (NullPointerException e) {
			e.printStackTrace();
			return new Rule(ruleName);
		}
	}

	// saving the rule in an XML file
	public void saveRule(File XMLFile) {
		
		if (XMLFile != null) {
			File document = XMLFile;

			if (document != null) {
				// left hand side
				Element rule = new Element("rule");
				rule.setAttribute("name", name);
				Element left = new Element("input");
				for (Component c : childrenList.getChildren()) {
					System.out.println(c.getName() +","+ c.getVar() + "#@##$%%%^^");
					Element documentElement = c.generateXMLElement();
					left.addContent(documentElement);
				}

				// right hand side
				Element right = new Element("output-action");
				for (Action a : actionList) {
					System.out.println(a.getActionName()+ "@#@#@#@#");
					a.setInputRule(childrenList);
					Element action = a.generateXMLAction();
					right.addContent(action);
				}

				rule.addContent(left);
				rule.addContent(right);

				XMLOutputter xmlOutput = new XMLOutputter();
				xmlOutput.setFormat(Format.getPrettyFormat());
				try {
					xmlOutput.output(rule, new FileWriter(document));
					JOptionPane.showMessageDialog(null, "Successfully Saved '"
							+ document.getName() + "'", "Save Success!",
							JOptionPane.INFORMATION_MESSAGE);
				} catch (Exception e) {
					e.printStackTrace();
					JOptionPane.showMessageDialog(null,
							"Error in saving file!", "Save Error",
							JOptionPane.ERROR_MESSAGE);
				}
			}

		}
	}
	
	public Element generateXMLRule(Element rule){
	
		System.out.println("entered generateXMLRule");
		
		Element xmlElement = new Element("rules");
		rule.setAttribute("name", name);
		
		return xmlElement;
	}

}
